//
//  LHPeerBrowser.m
//  GameKitDemo
//
//  Created by Xiaobin Li on 7/18/15.
//  Copyright (c) 2015 Xiaobin Li. All rights reserved.
//

#import "LHPeerBrowser.h"
#import <GameKit/GameKit.h>

@interface LHPeerBrowser ()<GKPeerPickerControllerDelegate, GKSessionDelegate>

- (void)receiveData:(NSData *)data fromPeer:(NSString *)peer inSession: (GKSession *)session context:(void *)context;

@end

@implementation LHPeerBrowser {
//    GKSession *_session;
}

+ (LHPeerBrowser *)sharedPeerBrowser
{
    static LHPeerBrowser *sharedPeerBrowser = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedPeerBrowser = [LHPeerBrowser new];
    });
    return sharedPeerBrowser;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
//        _session = [[GKSession alloc] initWithSessionID:nil displayName:nil sessionMode:GKSessionModePeer];
//        _session.delegate = self;
//        [_session setDataReceiveHandler:self withContext:NULL];
//        NSLog(@"_session=%p", _session);
    }
    return self;
}

- (void)show:(PeerType)type
{
    [self hide];
    
    GKPeerPickerController *picker = [[GKPeerPickerController alloc] init];
    picker.delegate = self;
    switch (type) {
        case PeerTypeNearby:
            picker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;
            break;
        case PeerTypeOnline:
            picker.connectionTypesMask = GKPeerPickerConnectionTypeOnline;
            break;
        default:
            break;
    }
    [picker show];
    
//    _session.available = YES;
}

- (void)hide
{
}

#pragma mark - GKPeerPickerControllerDelegate
/* Notifies delegate that a connection type was chosen by the user.
 */
- (void)peerPickerController:(GKPeerPickerController *)picker didSelectConnectionType:(GKPeerPickerConnectionType)type
{
    NSLog(@"connection type: %lu", (unsigned long)type);
}

/* Notifies delegate that the connection type is requesting a GKSession object.
 
 You should return a valid GKSession object for use by the picker. If this method is not implemented or returns 'nil', a default GKSession is created on the delegate's behalf.
 */
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (GKSession *)peerPickerController:(GKPeerPickerController *)picker sessionForConnectionType:(GKPeerPickerConnectionType)type
{
    return nil;
}

/* Notifies delegate that the peer was connected to a GKSession.
 */
- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session
{
    NSLog(@"%@: %p", peerID, session);
    
    [picker dismiss];
    picker.delegate = nil;
    
    [session setDataReceiveHandler:self withContext:NULL];
    NSString *msg = @"Hello";
    NSError *error = nil;
    NSLog(@"send %@ to %@ ...", msg, peerID);
    if (![session sendData:[NSData dataWithBytes:msg.UTF8String length:msg.length] toPeers:@[peerID] withDataMode:GKSendDataReliable error:&error])
    {
        NSLog(@"%@", error);
    }
}
#pragma clang diagnostic pop

/* Notifies delegate that the user cancelled the picker.
 */
- (void)peerPickerControllerDidCancel:(GKPeerPickerController *)picker
{
    picker.delegate = nil;
}

#pragma mark - GKSessionDelegate
/* Indicates a state change for the given peer.
 */
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state
{
    NSLog(@"peerId=%@, state: %i, session=%p", peerID, state, session);
//    GKPeerStateAvailable,    // not connected to session, but available for connectToPeer:withTimeout:
//    GKPeerStateUnavailable,  // no longer available
//    GKPeerStateConnected,    // connected to the session
//    GKPeerStateDisconnected, // disconnected from the session
//    GKPeerStateConnecting,   // waiting for accept, or deny response
    switch (state) {
        case GKPeerStateAvailable:
            [session connectToPeer:peerID withTimeout:10.f];
            break;
        case GKPeerStateConnected:
        {
            NSString *msg = @"Hello";
            NSError *error = nil;
            NSLog(@"send %@ to %@ ...", msg, peerID);
            if (![session sendData:[NSData dataWithBytes:msg.UTF8String length:msg.length] toPeers:@[peerID] withDataMode:GKSendDataReliable error:&error])
            {
                NSLog(@"%@", error);
            }
        }
            break;
        default:
            break;
    }
}
#pragma clang diagnostic pop

/* Indicates a connection request was received from another peer.
 
 Accept by calling -acceptConnectionFromPeer:
 Deny by calling -denyConnectionFromPeer:
 */
- (void)session:(GKSession *)session didReceiveConnectionRequestFromPeer:(NSString *)peerID
{
    NSLog(@"didReceiveConnectionRequestFromPeer: %@", peerID);
    [session acceptConnectionFromPeer:peerID error:nil];
}

/* Indicates a connection error occurred with a peer, which includes connection request failures, or disconnects due to timeouts.
 */
- (void)session:(GKSession *)session connectionWithPeerFailed:(NSString *)peerID withError:(NSError *)error
{
    NSLog(@"connectionWithPeerFailed, peerID=%@, error=%@", peerID, error);
}

/* Indicates an error occurred with the session such as failing to make available.
 */
- (void)session:(GKSession *)session didFailWithError:(NSError *)error
{
    
    NSLog(@"session didFailWithError: %@", error);
}

#pragma mark - recv handler
- (void)receiveData:(NSData *)data fromPeer:(NSString *)peer inSession:(GKSession *)session context:(void *)context
{
    NSLog(@"reveive data in session: %p", session);
    NSString *msg = [[NSString alloc] initWithBytes:data.bytes length:data.length encoding:NSUTF8StringEncoding];
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:peer message:msg delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil];
    if ([@"Hello" isEqualToString:msg])
    {
        NSString *response = [NSString stringWithFormat:@"Hi from %@", [UIDevice currentDevice].name];
        NSLog(@"send %@ to %@", response, peer);
        NSError *error = nil;
        if (![session sendData:[NSData dataWithBytes:response.UTF8String length:response.length] toPeers:@[peer] withDataMode:GKSendDataReliable error:&error])
        {
            NSLog(@"send data error: %@", error);
        }
        return;
    }
    [alert show];
}
@end
